package cn.iocoder.yudao.module.project.service.deliveryreceipt;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.project.dal.dataobject.deliveryreceiptdetail.DeliveryReceiptDetailDO;
import cn.iocoder.yudao.module.project.dal.dataobject.productprocesscompleted.ProductProcessCompletedDO;
import cn.iocoder.yudao.module.project.dal.mysql.deliveryreceiptdetail.DeliveryReceiptDetailMapper;
import cn.iocoder.yudao.module.project.dal.mysql.productprocesscompleted.ProductProcessCompletedMapper;
import cn.iocoder.yudao.module.project.service.workstation.WorkstationService;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.project.controller.admin.deliveryreceipt.vo.*;
import cn.iocoder.yudao.module.project.dal.dataobject.deliveryreceipt.DeliveryReceiptDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.project.dal.mysql.deliveryreceipt.DeliveryReceiptMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.project.config.projectDefine.HTTP_STATUS.ERROR_STATUS;
import static cn.iocoder.yudao.module.project.enums.ErrorCodeConstants.*;

/**
 * 产品拨交单 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class DeliveryReceiptServiceImpl implements DeliveryReceiptService {

    @Resource
    private DeliveryReceiptMapper deliveryReceiptMapper;

    @Resource
    private ProductProcessCompletedMapper productProcessCompletedMapper;

    @Resource
    private DeliveryReceiptDetailMapper deliveryReceiptDetailMapper;

    @Resource
    private WorkstationService workstationService;

    @Resource
    private PermissionApi permissionApi;

    @Resource
    private AdminUserApi adminUserApi;

    @Override
    public Integer createDeliveryReceipt(DeliveryReceiptSaveReqVO createReqVO) {
        // 插入
        DeliveryReceiptDO deliveryReceipt = BeanUtils.toBean(createReqVO, DeliveryReceiptDO.class);
        deliveryReceiptMapper.insert(deliveryReceipt);
        // 返回
        return deliveryReceipt.getId();
    }

    @Override
    public void updateDeliveryReceipt(DeliveryReceiptSaveReqVO updateReqVO) {
        // 校验存在
        validateDeliveryReceiptExists(updateReqVO.getId());
        // 更新
        DeliveryReceiptDO updateObj = BeanUtils.toBean(updateReqVO, DeliveryReceiptDO.class);
        deliveryReceiptMapper.updateById(updateObj);
    }

    @Override
    public void deleteDeliveryReceipt(Integer id) {
        // 校验存在
        validateDeliveryReceiptExists(id);
        // 删除
        deliveryReceiptMapper.deleteById(id);
    }

    private void validateDeliveryReceiptExists(Integer id) {
        if (deliveryReceiptMapper.selectById(id) == null) {
            throw exception(DELIVERY_RECEIPT_NOT_EXISTS);
        }
    }

    @Override
    public DeliveryReceiptDO getDeliveryReceipt(Integer id) {
        return deliveryReceiptMapper.selectById(id);
    }

    @Override
    public PageResult<DeliveryReceiptDO> getDeliveryReceiptPage(DeliveryReceiptPageReqVO pageReqVO) {
        Long loginUserId = WebFrameworkUtils.getLoginUserId();

        boolean adminFlag = permissionApi.hasAnyRoles(loginUserId, "longyi_admin");
        boolean managerFlag = permissionApi.hasAnyRoles(loginUserId, "longyi_manager");

        if(managerFlag || adminFlag){
            AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(loginUserId);
            Long deptId = adminUserRespDTO.getDeptId();
            pageReqVO.setOutDeptId(deptId.intValue());
        }else{
            pageReqVO.setOutDeptId(-1);
        }

        QueryWrapper<DeliveryReceiptDO> queryWrapper = new QueryWrapper<>();

        if(StringUtils.hasLength(pageReqVO.getDeliveryCode())){
            queryWrapper.like("delivery_code", pageReqVO.getDeliveryCode());
        }

        if(null != pageReqVO.getSubmitTime() && pageReqVO.getSubmitTime().length == 2){
            LocalDateTime[] submitTime = pageReqVO.getSubmitTime();
            queryWrapper.ge("submit_time", LocalDateTimeUtil.format(submitTime[0], "yyyy-MM-dd HH:mm:ss")).le("submit_time", LocalDateTimeUtil.format(submitTime[1], "yyyy-MM-dd HH:mm:ss"));
        }

        /**
        if(StringUtils.hasLength(pageReqVO.getRemark())){
            queryWrapper.like("remark", pageReqVO.getRemark());
        }

        if(StringUtils.hasLength(pageReqVO.getOutDeptName())){
            queryWrapper.like("out_dept_name", pageReqVO.getOutDeptName());
        }

        if(StringUtils.hasLength(pageReqVO.getRecvDeptName())){
            queryWrapper.like("recv_dept_name", pageReqVO.getRecvDeptName());
        }
         **/

        if(null != pageReqVO.getOutDeptId() && null != pageReqVO.getOutDeptId()){
            queryWrapper.and(queryWrapper1 -> queryWrapper1.eq("out_dept_id", pageReqVO.getOutDeptId()).or().eq("recv_dept_id", pageReqVO.getOutDeptId()));
        }
        queryWrapper.orderByDesc("create_time");

        PageResult<DeliveryReceiptDO> pageResult = deliveryReceiptMapper.selectPage(pageReqVO, queryWrapper);

        List<DeliveryReceiptDO> list = pageResult.getList();
        list.forEach(deliveryReceiptDO -> {
            deliveryReceiptDO.setSubmitTimeStr(DateUtils.format(deliveryReceiptDO.getSubmitTime(), DateUtils.DATE_FORMAT_19));
        });

        return pageResult;
    }

    @Override
    @Transactional
    public synchronized Integer generateDeliveryReceipt(DeliveryReceiptConditionVO deliveryReceiptConditionVO) {

        DictDataRespDTO workstationDept = workstationService.getWorkstationDept(deliveryReceiptConditionVO.getDeptId());
        if(ObjectUtils.isEmpty(workstationDept)){
            return null;
        }

        String deptName = null;
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(loginUserId);
        if(!ObjectUtils.isEmpty(adminUserRespDTO.getRemark())){
            deptName = adminUserRespDTO.getRemark();
        }

        DictDataRespDTO nextWorkstationDept = null;

        if("A课".equalsIgnoreCase(workstationDept.getLabel())){
            nextWorkstationDept = workstationService.getWorkstationDept("B课");
        }else if ("B课".equalsIgnoreCase(workstationDept.getLabel())){
            nextWorkstationDept = workstationService.getWorkstationDept("C课");
        }else if ("C课".equalsIgnoreCase(workstationDept.getLabel())){
            nextWorkstationDept = workstationService.getWorkstationDept("包装交接");
        }

        DeliveryReceiptSaveReqVO deliveryReceiptSaveReqVO = new DeliveryReceiptSaveReqVO();
        deliveryReceiptSaveReqVO.setOutDeptId(deliveryReceiptConditionVO.getDeptId());
        deliveryReceiptSaveReqVO.setOutDeptName(workstationDept.getLabel());
        deliveryReceiptSaveReqVO.setRecvDeptId(Integer.parseInt(nextWorkstationDept.getValue()));
        deliveryReceiptSaveReqVO.setRecvDeptName(nextWorkstationDept.getLabel());
        deliveryReceiptSaveReqVO.setSubmitTime(LocalDateTime.now());

        if(!ObjectUtils.isEmpty(deptName) && "B课外协1".equalsIgnoreCase(deptName)){
            deliveryReceiptSaveReqVO.setRemark(deptName);
        }else {
            deliveryReceiptSaveReqVO.setRemark(workstationDept.getLabel());
        }

        String currentDateStr = DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);

        QueryWrapper<DeliveryReceiptDO> deliveryReceiptDOQueryWrapper = new QueryWrapper<>();
        String deliveryCode = "BJ" + currentDateStr;
        deliveryReceiptDOQueryWrapper.likeRight("delivery_code", deliveryCode);
        deliveryReceiptDOQueryWrapper.orderByDesc("create_time");
        deliveryReceiptDOQueryWrapper.last("limit 1");
        DeliveryReceiptDO lastDeliveryReceiptDO = deliveryReceiptMapper.selectOne(deliveryReceiptDOQueryWrapper);
        if(ObjectUtils.isEmpty(lastDeliveryReceiptDO)){
            deliveryReceiptSaveReqVO.setDeliveryCode(deliveryCode + "0001");
        }else{
            String lastDeliveryCode = lastDeliveryReceiptDO.getDeliveryCode();
            String lastIndex = lastDeliveryCode.substring(lastDeliveryCode.length() - 4);
            int index = Integer.parseInt(lastIndex) + 1;
            deliveryReceiptSaveReqVO.setDeliveryCode(deliveryCode + String.format("%04d", index));
        }

        QueryWrapper<ProductProcessCompletedDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dept_id", deliveryReceiptConditionVO.getDeptId());
        queryWrapper.eq("delivery_status", "0");

        if(!ObjectUtils.isEmpty(deliveryReceiptConditionVO.getExcludeCompletedProcessIdList())){
            queryWrapper.notIn("id", deliveryReceiptConditionVO.getExcludeCompletedProcessIdList());
        }
        if(!ObjectUtils.isEmpty(deliveryReceiptConditionVO.getOrderId())){
            queryWrapper.eq("order_id", deliveryReceiptConditionVO.getOrderId());
        }
        if(!ObjectUtils.isEmpty(deliveryReceiptConditionVO.getInternalCode())){
            queryWrapper.eq("internal_code", deliveryReceiptConditionVO.getInternalCode());
        }
        if(!ObjectUtils.isEmpty(deliveryReceiptConditionVO.getProductionCode())){
            queryWrapper.eq("production_code", deliveryReceiptConditionVO.getProductionCode());
        }
        if(!ObjectUtils.isEmpty(deliveryReceiptConditionVO.getType())){
            queryWrapper.eq("type", deliveryReceiptConditionVO.getType());
        }

        List<ProductProcessCompletedDO> productProcessCompletedDOList = productProcessCompletedMapper.selectList(queryWrapper);
        if(ObjectUtils.isEmpty(productProcessCompletedDOList)){
            return null;
        }

        List<DeliveryReceiptDO> existsDeliveryReceiptDOList = deliveryReceiptMapper.selectList(DeliveryReceiptDO::getDeliveryCode, deliveryReceiptSaveReqVO.getDeliveryCode());

        if(!ObjectUtils.isEmpty(existsDeliveryReceiptDOList)){
            return -1;
        }

        Integer deliveryReceiptId = createDeliveryReceipt(deliveryReceiptSaveReqVO);

        List<DeliveryReceiptDetailDO> deliveryReceiptDetailDOList = new ArrayList<>();


        List<DeliveryReceiptDetailDO> existsDeliveryReceiptDetailDOList = deliveryReceiptDetailMapper.selectList(DeliveryReceiptDetailDO::getOrderId, deliveryReceiptConditionVO.getOrderId());
        List<Integer> existsProductProcessCompletedIdList = null;
        if(!ObjectUtils.isEmpty(existsDeliveryReceiptDetailDOList)){
            existsProductProcessCompletedIdList = existsDeliveryReceiptDetailDOList.stream().map(deliveryReceiptDetailDO -> deliveryReceiptDetailDO.getProductProcessCompletedId()).collect(Collectors.toList());
        }

        for(ProductProcessCompletedDO productProcessCompletedDO : productProcessCompletedDOList){
            if(!ObjectUtils.isEmpty(existsProductProcessCompletedIdList)){
                if(existsProductProcessCompletedIdList.contains(productProcessCompletedDO.getId())){
                    throw new ServiceException(new ErrorCode(ERROR_STATUS, "请不用重复生成拨交单"));
                }
            }

            DeliveryReceiptDetailDO deliveryReceiptDetailDO = new DeliveryReceiptDetailDO();
            deliveryReceiptDetailDO.setDeliveryReceiptId(deliveryReceiptId);
            deliveryReceiptDetailDO.setProductProcessCompletedId(productProcessCompletedDO.getId());
            deliveryReceiptDetailDO.setOrderId(productProcessCompletedDO.getOrderId());
            deliveryReceiptDetailDO.setInternalCode(productProcessCompletedDO.getInternalCode());
            deliveryReceiptDetailDO.setProductionCode(productProcessCompletedDO.getProductionCode());
            deliveryReceiptDetailDO.setType(productProcessCompletedDO.getType());
            deliveryReceiptDetailDO.setLastCollectionTime(productProcessCompletedDO.getLastCollectionTime());
            deliveryReceiptDetailDO.setOutDeptId(deliveryReceiptSaveReqVO.getOutDeptId());
            deliveryReceiptDetailDO.setOutDeptName(deliveryReceiptSaveReqVO.getOutDeptName());
            deliveryReceiptDetailDO.setRecvDeptId(deliveryReceiptSaveReqVO.getRecvDeptId());
            deliveryReceiptDetailDO.setRecvDeptName(deliveryReceiptSaveReqVO.getRecvDeptName());
            deliveryReceiptDetailDO.setSubmitTime(deliveryReceiptSaveReqVO.getSubmitTime());
            deliveryReceiptDetailDO.setRemark(productProcessCompletedDO.getRemark());//客户要看规格
            deliveryReceiptDetailDO.setSubmitDeptName(deliveryReceiptSaveReqVO.getRemark());

            deliveryReceiptDetailDOList.add(deliveryReceiptDetailDO);
        }

        deliveryReceiptDetailMapper.insertBatch(deliveryReceiptDetailDOList);

        DeliveryReceiptDO deliveryReceiptDO = new DeliveryReceiptDO();
        Long orderTotalCount = productProcessCompletedDOList.stream().map(productProcessCompletedDO -> productProcessCompletedDO.getOrderId()).distinct().count();
        deliveryReceiptDO.setOrderTotal(orderTotalCount.intValue());
        deliveryReceiptDO.setDeliveryCount(deliveryReceiptDetailDOList.size());
        deliveryReceiptDO.setId(deliveryReceiptId);
        deliveryReceiptMapper.updateById(deliveryReceiptDO);

        ProductProcessCompletedDO productProcessCompletedDO = new ProductProcessCompletedDO();
        productProcessCompletedDO.setDeliveryStatus("1");
        //productProcessCompletedDO.setDeptId(Integer.parseInt(nextWorkstationDept.getValue()));
        //productProcessCompletedDO.setDeptName(nextWorkstationDept.getLabel());
        productProcessCompletedMapper.update(productProcessCompletedDO, queryWrapper);


        return deliveryReceiptId;
    }

    @Override
    public PageResult<DeliveryReceiptDO> getDeliveryReceiptReport(DeliveryReceiptPageReqVO pageReqVO) {
        Page<DeliveryReceiptPageReqVO> pageParam = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<DeliveryReceiptDO> list = deliveryReceiptMapper.getDeliveryReceiptReport(pageParam, pageReqVO);

        list.forEach(deliveryReceiptDO -> {
            deliveryReceiptDO.setSubmitTimeStr(DateUtils.format(deliveryReceiptDO.getSubmitTime(), DateUtils.DATE_FORMAT_19));
        });

        PageResult<DeliveryReceiptDO> pageResult = new PageResult<>(list, pageParam.getTotal());
        return pageResult;
    }

}